package binding

import (
	"mime/multipart"
	"strings"
	"time"
)

func multiSource(form *multipart.Form) Source {
	return multiPartValuer{mulForm: form}
}

type multiPartValuer struct {
	mulForm *multipart.Form
}

func (ver multiPartValuer) Get(key string) (v Source, err error) {
	fv := formValuer{}
	for name, values := range ver.mulForm.Value {
		if strings.HasPrefix(name, key) {
			if sub := name[len(key):]; len(sub) == 0 || sub[0] == '.' || sub[0] == '[' {
				if len(sub) > 0 && sub[0] == '.' {
					sub = sub[1:]
				}
				fv[sub] = append(fv[sub], values...)
			}
		}
	}

	files := map[string][]*multipart.FileHeader{}
	for name, values := range ver.mulForm.File {
		if strings.HasPrefix(name, key) {
			if sub := name[len(key):]; len(sub) == 0 || sub[0] == '.' || sub[0] == '[' {
				if len(sub) > 0 && sub[0] == '.' {
					sub = sub[1:]
				}
				files[sub] = append(files[sub], values...)
			}
		}
	}

	if len(fv) == 0 && len(files) == 0 {
		err = ErrNoValue
	} else {
		v = multiPartValuer{mulForm: &multipart.Form{Value: fv, File: files}}
	}
	return
}

func (ver multiPartValuer) Map(iter func(key string, valuer Source)) {
	formValuer(ver.mulForm.Value).Map(iter)
}

func (ver multiPartValuer) Array(iter func(index int, valuer Source) bool, beforeFs ...func(size int)) {
	formValuer(ver.mulForm.Value).Array(iter, beforeFs...)
}

func (ver multiPartValuer) String() (s string, err error) {
	return formValuer(ver.mulForm.Value).String()
}

func (ver multiPartValuer) Int() (i int64, err error) {
	return formValuer(ver.mulForm.Value).Int()
}

func (ver multiPartValuer) Uint() (u uint64, err error) {
	return formValuer(ver.mulForm.Value).Uint()
}

func (ver multiPartValuer) Float() (f float64, err error) {
	return formValuer(ver.mulForm.Value).Float()
}

func (ver multiPartValuer) Bool() (b bool, err error) {
	return formValuer(ver.mulForm.Value).Bool()
}

func (ver multiPartValuer) Time() (t time.Time, err error) {
	return formValuer(ver.mulForm.Value).Time()
}

func (ver multiPartValuer) Duration() (d time.Duration, err error) {
	return formValuer(ver.mulForm.Value).Duration()
}

func (ver multiPartValuer) File() (f *multipart.FileHeader, err error) {
	if ver.mulForm.File != nil {
		if fs := ver.mulForm.File[""]; len(fs) > 0 {
			return fs[0], nil
		}
	}
	return nil, ErrNoValue
}

func (ver multiPartValuer) Files() (f []*multipart.FileHeader, err error) {
	if ver.mulForm.File != nil {
		if fs := ver.mulForm.File[""]; len(fs) > 0 {
			return fs, nil
		}
	}
	return nil, ErrNoValue
}

var _ Source = multiPartValuer{}
